<!-- 搜索框 -->

<template>
  <div class="container">
    <div class="search-container glass">
      <input
        ref="inputRef"
        autofocus
        class="search-input"
        type="text"
        placeholder="input keywords"
        v-model="input"
        @keyup.enter="openSearchResult"
        @input="getKeywordList"
        @focus="getKeywordList"
        tabindex="0"
      />
      <div class="icon" @click="openSearchResult" tabindex="1">
        <svg
          viewBox="0 0 1024 1024"
          version="1.1"
          xmlns="http://www.w3.org/2000/svg"
          width="50%"
          height="50%"
        >
          <path
            d="M859.423786 995.395627l-169.615707-169.615707a445.241232 445.241232 0 0 1-241.263722 71.355573 448.531191 448.531191 0 1 1 448.604302-448.604302 445.387452 445.387452 0 0 1-71.428684 241.263722l169.615707 169.615707a96.139938 96.139938 0 1 1-135.911896 135.985007zM138.337699 448.01942a309.767996 309.767996 0 1 0 619.535993 0 309.767996 309.767996 0 0 0-619.535993 0z"
          ></path>
        </svg>
      </div>
    </div>
    <ul class="result glass" ref="resultContainer">
      <li
        v-for="(item, index) in searchList"
        :key="item.url"
        class="item"
        :class="{
          active: index === activeIndex,
        }"
        :tabindex="index + 2"
        @click="handleSearchCurrent(item, index, $event)"
      >
        <span v-html="item.keyword" class="keyword"></span>
      </li>
    </ul>
  </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref } from "vue";
import { EMessageType } from "../../../utils";
// 搜索结果容器
const resultContainer = ref<HTMLElement>();

const inputRef = ref<HTMLInputElement>();
const input = ref<string>("");

/** 获取关联词列表 */
const getKeywordList = async () => {
  activeIndex.value = -1;
  const result = await chrome.runtime.sendMessage({
    id: EMessageType.Keyword,
    params: {
      keyword: input.value,
    },
  });

  const dom = new DOMParser().parseFromString(result, "text/html");
  const list = dom.querySelector("ul");
  if (list && resultContainer.value) {
    findSearchResult(list);
  }
};
/** 跳转搜索界面 */
const openSearchResult = async () => {
  const result = await chrome.runtime.sendMessage({
    id: EMessageType.Search,
    params: {
      keyword: input.value,
    },
  });

  result && window.open(result, "_blank");
  input.value = "";
  searchList.value = [];
};

interface ISearchItem {
  url: string;
  isDelete: boolean;
  keyword: string | undefined;
  text: string;
}
const searchList = ref<ISearchItem[]>([]);

const findSearchResult = (ul: HTMLUListElement) => {
  const domList = ul.querySelectorAll(" li");
  searchList.value = [];
  for (let i = 0; i < domList.length; i++) {
    const li = domList[i];
    const url = li.getAttribute("url") as string;
    const isDelete = li.parentElement?.className === "sa_prnt";
    const textDom = li.querySelector(".sa_tm_text") as HTMLElement;
    if (!textDom) continue;
    searchList.value.push({
      url: url,
      isDelete,
      keyword: textDom?.innerHTML,
      text: textDom?.innerText,
    });
  }
};

const activeIndex = ref<number>(-1);
const setActiveIndex = (e: KeyboardEvent) => {
  if (e.key === "ArrowDown") {
    activeIndex.value = (activeIndex.value + 1) % searchList.value.length;
  }
  if (e.key === "ArrowUp") {
    activeIndex.value < 0 && (activeIndex.value = 0);
    activeIndex.value =
      activeIndex.value % searchList.value.length === 0
        ? searchList.value.length - 1
        : activeIndex.value - 1;
  }

  if (e.key === "Escape") {
    searchList.value = [];
    inputRef.value?.blur();
    return;
  }

  if (activeIndex.value < 0) return;

  input.value = searchList.value[activeIndex.value]?.text;
};
onMounted(() => {
  window.addEventListener("keyup", setActiveIndex);
});
onUnmounted(() => {
  window.removeEventListener("keyup", setActiveIndex);
});

const handleSearchCurrent = (_: ISearchItem, index: number, event: Event) => {
  const currentKeyword = (event.target as HTMLSpanElement).innerText;
  activeIndex.value = index;
  input.value = currentKeyword;
  openSearchResult();
};
</script>

<style lang="scss" scoped>
@import "../../style/function.scss";

.container {
  min-width: 400px;
  width: 40%;
  position: fixed;
  left: 50%;
  top: 20%;
  transform: translateX(-50%);

  .search-container {
    padding: size(l) size(3);
    border-radius: 9999px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    animation: lightSpeedInLeft;
    animation-duration: 1s;

    .search-input {
      flex: 1;
      padding: size(0.5) size(xxxl);
      border: 2px solid #000;
      outline: none;
      border-radius: 9999px;
      caret-color: var(--primary-color);
      transition: border-color 0.5s;
      background-color: var(--nature-bg-1);

      &:focus {
        border: 2px solid var(--primary-color);
      }
    }

    .icon {
      height: size(3.6);
      width: size(3.6);
      border-radius: 50%;
      margin-left: size(s);
      display: flex;
      justify-content: center;
      align-items: center;
      color: var(--primary-color);
      background-color: var(--primary-color);
      cursor: pointer;

      &:hover {
        animation-name: rubberBand;
        animation-duration: 1s;
      }

      svg {
        fill: #ddd;
      }
    }
  }

  .result {
    width: 100%;
    margin-top: size(m);
    border-radius: size();
    padding: 0px size();
    border: 0px;
    .item {
      display: flex;
      align-items: center;
      justify-content: flex-start;
      padding: size(0.5) size(2);
      cursor: pointer;
      margin-top: size(0.5);
      border-radius: 4px;

      & + .item {
        margin-bottom: size(0.5);
      }

      &:focus {
        background-color: var(--nature-bg-1);
      }

      &:hover {
        background-color: var(--nature-bg-1);
      }

      .keyword {
        flex: 1;
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
        color: var(--nature-color-1);
      }
    }

    .active {
      background-color: var(--nature-bg-1);
    }
  }
}
</style>
